package com.jcark.arch.net.state

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.*
import android.os.Build
import com.jcark.arch.net.NetworkUtils
import com.jcark.arch.net.state.NetStateUtils.getAPNType
import java.lang.reflect.InvocationTargetException

/**
 * AnnotationApplication
 * Created by anonyper on 2019/6/10.
 */
object NetWorkMonitorManager {
    private var context: Context? = null

    /**
     * 存储接受网络状态变化消息的方法的map
     */
    var netWorkStateChangedCallbacks: ArrayList<NetworkCallback> = arrayListOf()

    /**
     * 初始化 传入application
     *
     * @param application
     */
    fun init(context: Context?) {
        if (context == null) {
            throw NullPointerException("context can not be null")
        }
        this.context = context
        initMonitor()
    }

    /**
     * 初始化网络监听 根据不同版本做不同的处理
     */
    private fun initMonitor() {
        val connectivityManager =
            context!!.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { //API 大于26时
            connectivityManager.registerDefaultNetworkCallback(networkCallback)
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { //API 大于21时
            val builder = NetworkRequest.Builder()
            val request = builder.build()
            connectivityManager.registerNetworkCallback(request, networkCallback)
        } else { //低版本
            val intentFilter = IntentFilter()
            intentFilter.addAction(ANDROID_NET_CHANGE_ACTION)
            context!!.registerReceiver(receiver, intentFilter)
        }
    }

    /**
     * 反注册广播
     */
    private fun onDestroy() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            context!!.unregisterReceiver(receiver)
        }
    }

    /**
     * 注入
     * @param object
     */
    fun register(networkCallback: NetworkCallback) {
//        if (context == null) {
//            throw NullPointerException("application can not be null,please call the method init(Application application) to add the Application")
//        }
//        if (`object` != null) {
//            val netWorkStateReceiverMethod = findMethod(`object`)
//            if (netWorkStateReceiverMethod != null) {
//                netWorkStateChangedMethodMap!![`object`] = netWorkStateReceiverMethod
//            }
//        }
        if (!netWorkStateChangedCallbacks.contains(networkCallback)) {
            netWorkStateChangedCallbacks.add(networkCallback)
        }
    }

    /**
     * 删除
     *
     * @param object
     */
    fun unregister(networkCallback: NetworkCallback) {
        if (netWorkStateChangedCallbacks.contains(networkCallback)) {
            netWorkStateChangedCallbacks.remove(networkCallback)
        }
//        if (`object` != null && netWorkStateChangedMethodMap != null) {
//            netWorkStateChangedMethodMap!!.remove(`object`)
//        }
    }

    /**
     * 网络状态发生变化，需要去通知更改
     * @param netWorkState
     */
    private fun postNetState(netWorkState: NetWorkState) {
//        val set: Set<Any> = netWorkStateChangedMethodMap!!.keys
//        val iterator: Iterator<*> = set.iterator()
//        while (iterator.hasNext()) {
//            val any = iterator.next()!!
//            val netWorkStateReceiverMethod = netWorkStateChangedMethodMap!![any]
//            invokeMethod(netWorkStateReceiverMethod, netWorkState)
//        }
        for (netWorkStateChangedCallback in netWorkStateChangedCallbacks) {
            netWorkStateChangedCallback.onNetChange(netWorkState)
        }
    }

    /**
     * 具体执行方法
     *
     * @param netWorkStateReceiverMethod
     * @param netWorkState
     */
    private fun invokeMethod(
        netWorkStateReceiverMethod: NetWorkStateReceiverMethod?,
        netWorkState: NetWorkState
    ) {
        if (netWorkStateReceiverMethod != null) {
            try {
                val netWorkStates = netWorkStateReceiverMethod.netWorkState
                for (myState in netWorkStates) {
                    if (myState == netWorkState) {
                        netWorkStateReceiverMethod.method
                            ?.invoke(netWorkStateReceiverMethod.any, netWorkState)
                        return
                    }
                }
            } catch (e: IllegalAccessException) {
                e.printStackTrace()
            } catch (e: InvocationTargetException) {
                e.printStackTrace()
            }
        }
    }

    /**
     * 找到对应的方法
     *
     * @param `object`
     * @return
     */
    private fun findMethod(any: Any?): NetWorkStateReceiverMethod? {
        var targetMethod: NetWorkStateReceiverMethod? = null
        if (any != null) {
            val myClass: Class<*> = any.javaClass
            //获取所有的方法
            val methods = myClass.declaredMethods
            for (method in methods) {
                //如果参数个数不是1个 直接忽略
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    if (method.parameterCount != 1) {
                        continue
                    }
                }
                //获取方法参数
                val parameters = method.parameterTypes
                if (parameters == null || parameters.size != 1) {
                    continue
                }
                //参数的类型需要时NetWorkState类型
                if (parameters[0].name == NetWorkState::class.java.name) {
                    //是NetWorkState类型的参数
                    val netWorkMonitor = method.getAnnotation(
                        NetWorkMonitor::class.java
                    )
                    targetMethod = NetWorkStateReceiverMethod()
                    //如果没有添加注解，默认就是所有网络状态变化都通知
                    if (netWorkMonitor != null) {
                        val netWorkStates = netWorkMonitor.monitorFilter
                        targetMethod.netWorkState = netWorkStates
                    }
                    targetMethod.method = method
                    targetMethod.any = any
                    //只添加第一个符合的方法
                    return targetMethod
                }
            }
        }
        return targetMethod
    }

    var receiver: BroadcastReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            if (intent.action.equals(ANDROID_NET_CHANGE_ACTION, ignoreCase = true)) {
                //网络发生变化 没有网络-0：WIFI网络1：4G网络-4：3G网络-3：2G网络-2
                val netType = getAPNType(context)
                var netWorkState = NetWorkState.NONE
                netWorkState = when (netType) {
                    0 -> NetWorkState.NONE
                    1 -> NetWorkState.WIFI
                    else -> NetWorkState.GPRS
                }
                postNetState(netWorkState)
            }
        }
    }
    var networkCallback: ConnectivityManager.NetworkCallback =
        object : ConnectivityManager.NetworkCallback() {
            /**
             * 网络可用的回调连接成功
             */
            override fun onAvailable(network: Network) {
                super.onAvailable(network)
                val netType = getAPNType(context!!)
                var netWorkState = NetWorkState.NONE
                netWorkState = when (netType) {
                    0 -> NetWorkState.NONE
                    1 -> NetWorkState.WIFI
                    else -> NetWorkState.GPRS
                }
                postNetState(netWorkState)
            }

            /**
             * 网络不可用时调用和onAvailable成对出现
             */
            override fun onLost(network: Network) {
                super.onLost(network)
                postNetState(NetWorkState.NONE)
            }

            /**
             * 在网络连接正常的情况下，丢失数据会有回调 即将断开时
             */
            override fun onLosing(network: Network, maxMsToLive: Int) {
                super.onLosing(network, maxMsToLive)
            }

            /**
             * 网络功能更改 满足需求时调用
             * @param network
             * @param networkCapabilities
             */
            override fun onCapabilitiesChanged(
                network: Network,
                networkCapabilities: NetworkCapabilities
            ) {
                super.onCapabilitiesChanged(network, networkCapabilities)
            }

            /**
             * 网络连接属性修改时调用
             * @param network
             * @param linkProperties
             */
            override fun onLinkPropertiesChanged(network: Network, linkProperties: LinkProperties) {
                super.onLinkPropertiesChanged(network, linkProperties)
            }

            /**
             * 网络缺失network时调用
             */
            override fun onUnavailable() {
                super.onUnavailable()
            }
        }

    private const val ANDROID_NET_CHANGE_ACTION = "android.net.conn.CONNECTIVITY_CHANGE"

    fun isNetworkAvailable(): Boolean {
        return if (null != context) NetworkUtils.isNetworkAvailable(context!!) else false
    }
}